﻿using System;
using System.IO;
using System.IO.Compression;
using System.Threading;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;

using PickGold.Handler;
using PickGold.Arguments;
using PickGold.Exceptions;

using HsjCommon = PickGold.Common;

namespace PickGold.Callers
{
	/// <summary>
	/// 线程运行器
	/// </summary>
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	public class CRunnerBase : IDisposable
	{
		private int _RanTimes;// volatile
		private int _ErrorTimes;// volatile
		private int _ThreadState;// volatile
		private bool _IsDisposed;
		private object _Tag;
		private ERunnerFlags _Flags;
		private List<IDelegate> _HandlerList;// volatile
		private Dictionary<Thread, EventWaitHandle> _Dictionary;// volatile

		/// <summary>
		/// 同步对象
		/// </summary>
		protected object _SyncRoot;

		/// <summary>
		/// 实例化一线程运行器对象
		/// </summary>
		/// <param name="flags">运行方式</param>
		protected CRunnerBase(ERunnerFlags flags)
		{
			this._Flags = flags;
			this._HandlerList = new List<IDelegate>();
			this._Dictionary = new Dictionary<Thread, EventWaitHandle>();

			this._SyncRoot = new object();
		}

		/// <summary>
		/// 线程错误
		/// </summary>
		public event HErrorEventHandler Error;

		/// <summary>
		/// 当前委托
		/// </summary>
		public virtual IDelegate Handler
		{
			set
			{
				if (this._HandlerList.Count == 0)
					this._HandlerList.Add(value);
				else
					this._HandlerList[0] = value;
			}
			get
			{
				if (this._HandlerList.Count == 0)
					return null;

				return this._HandlerList[0];
			}
		}

		#region ThreadState

		/// <summary>
		/// 是否已开始并运行
		/// </summary>
		public bool IsStarted
		{
			get
			{
				if (this._ThreadState == (int)ThreadState.Running)
					return true;

				return false;
			}
		}

		/// <summary>
		/// 是否已转让或阻塞
		/// </summary>
		public bool IsSleep
		{
			get
			{
				if (this._ThreadState == (int)ThreadState.WaitSleepJoin)
					return true;

				return false;
			}
		}

		/// <summary>
		/// 是否已暂停或阻塞
		/// </summary>
		public bool IsPaused
		{
			get
			{
				if (this._ThreadState == (int)ThreadState.Suspended)
					return true;

				return false;
			}
		}

		/// <summary>
		/// 是否已停止或销毁
		/// </summary>
		public bool IsStopped
		{
			get
			{
				if (this._ThreadState == (int)ThreadState.Stopped)
					return true;

				return false;
			}
		}

		#endregion

		/// <summary>
		/// 设置或获取存储的附加数据
		/// </summary>
		public object Tag
		{
			set
			{
				this._Tag = value;
			}
			get
			{
				return this._Tag;
			}
		}

		/// <summary>
		/// 启动
		/// </summary>
		public void Start()
		{
			if (this._IsDisposed)
				throw new ObjectDisposedException(this.GetType().Name);

			foreach (var item in this._Dictionary)
			{
				if (item.Value == null)
				{
					this._Dictionary[item.Key] = new ManualResetEvent(true);
					item.Key.Start();
				}
				item.Value.Set();
			}
		}

		/// <summary>
		/// 暂停
		/// </summary>
		public void Pause()
		{
			if (this._IsDisposed)
				throw new ObjectDisposedException(this.GetType().Name);

			foreach (var handler in this._Dictionary.Values)
			{
				if (handler != null)
					handler.Reset();
			}
		}

		/// <summary>
		/// 停止并销毁
		/// </summary>
		public void Stop()
		{
			if (this._IsDisposed)
				throw new ObjectDisposedException(this.GetType().Name);

			foreach (var thread in this._Dictionary.Keys)
			{
				if (thread == Thread.CurrentThread)
					throw new RunnerCancelException();
			}

			foreach (var handler in this._Dictionary.Values)
			{
				if (handler != null)
					handler.Close();
			}
		}

		/// <summary>
		/// 线程错误
		/// </summary>
		/// <param name="e">错误参数</param>
		protected virtual void OnError(CErrorEventArgs e)
		{
			if (this.Error != null)
			{
				this.Error(this, e);
				return;
			}

			e.ThrowError = false;
		}

		/// <summary>
		/// 运行
		/// </summary>
		protected virtual void Run()
		{
		Label:
			if (this._IsDisposed)
				throw new ObjectDisposedException(this.GetType().Name);

			if (this._HandlerList == null || this._HandlerList.Count == 0)
				return;

			Interlocked.Exchange(ref this._ThreadState, (int)ThreadState.Running);
			try
			{
				this._HandlerList[0].Invoke();
				Interlocked.Increment(ref this._RanTimes);
			}
			catch (RunnerCancelException x)
			{
				//continue;
			}
			catch (Exception x)
			{
				Tracker.WriteError(x);
				Interlocked.Increment(ref this._ErrorTimes);
				CErrorEventArgs e = new CErrorEventArgs(this._HandlerList[0].Handler.Method);
				e.Error = x;
				this.OnError(e);
				if (e.ThrowError)
					throw;
			}
			finally
			{
				Interlocked.Exchange(ref this._ThreadState, (int)ThreadState.WaitSleepJoin);
			}
			if (this.GetType() != typeof(CRunnerBase))
				return;

			foreach (var handle in this._Dictionary.Values)
			{
				if (handle != null)
					handle.Reset();
			}
			goto Label;
		}

		/// <summary>
		/// 是否已请求停止，如果未停止，则等待暂停信号
		/// </summary>
		/// <returns></returns>
		/// <exception cref="PickGold.CRunnerCancelException">线程已退出</exception>
		/// <exception cref="System.ObjectDisposedException">对象已销毁</exception>
		public bool IsStopedAndWaitPause()
		{
			EventWaitHandle handle;
			lock (this._SyncRoot)
			{
				if (this._IsDisposed)
					throw new ObjectDisposedException(this.GetType().Name);

				if (!this._Dictionary.ContainsKey(Thread.CurrentThread))
					return false;

				handle = this._Dictionary[Thread.CurrentThread];
				if (handle == null)
					throw new RunnerCancelException();

				if (this._ThreadState == (int)ThreadState.Stopped)
					return true;

				if (this._ThreadState != (int)ThreadState.Suspended)
					return false;
			}

			handle.WaitOne();
			lock (this._SyncRoot)
			{
				if (!this._Dictionary.ContainsValue(handle))
					throw new RunnerCancelException();
			}
			return false;
		}

		#region IDisposable 成员

		/// <summary>
		/// 资源是否已释放
		/// </summary>
		public bool IsDisposed
		{
			get
			{
				return this._IsDisposed;
			}
		}

		/// <summary>
		/// 销毁
		/// </summary>
		public void Dispose()
		{
			lock (this._SyncRoot)
				this.Dispose(true);
		}

		/// <summary>
		/// 销毁
		/// </summary>
		/// <param name="disposing">是否为手工销毁</param>
		protected virtual void Dispose(bool disposing)
		{
			if (this._IsDisposed)
				return;

			this._IsDisposed = true;
			//throw new NotImplementedException();
			this.Stop();
			var ls = new List<Thread>(this._Dictionary.Keys);
			foreach (var item in ls)
			{
				var handle = this._Dictionary[item];
				this._Dictionary[item] = null;
				if (handle != null)
				{
					handle.Set();
					handle.Close();
				}

				item.Interrupt();
			}
			ls.Clear();
			this._Dictionary.Clear();
			this._HandlerList.Clear();
		}

		/// <summary>
		/// 销毁
		/// </summary>
		~CRunnerBase()
		{
			lock (this._SyncRoot)
				this.Dispose(false);
		}

		#endregion

		/// <summary>
		/// 将当前线程挂起指定的时间。
		/// </summary>
		/// <param name="millisecondsTimeout">线程被阻塞的毫秒数。指定零 (0) 以指示应挂起此线程以使其他等待线程能够执行。指定 System.Threading.Timeout.Infinite 以无限期阻止线程。</param>
		/// <exception cref="System.ArgumentOutOfRangeException">超时值为负且不等于 System.Threading.Timeout.Infinite。</exception>
		/// <returns>当前线程</returns>
		public static Thread Sleep(int millisecondsTimeout)
		{
			Thread.Sleep(millisecondsTimeout);
			return Thread.CurrentThread;
		}
		/// <summary>
		/// 将当前线程阻塞指定的时间。
		/// </summary>
		/// <param name="timeout">设置为线程被阻塞的时间量的 System.TimeSpan。指定零以指示应挂起此线程以使其他等待线程能够执行。指定 System.Threading.Timeout.Infinite 以无限期阻止线程。</param>
		/// <exception cref="System.ArgumentOutOfRangeException">timeout 的值为负，而且不等于 System.Threading.Timeout.Infinite（以毫秒为单位），或者大于 System.Int32.MaxValue 毫秒。</exception>
		/// <returns>当前线程</returns>
		public static Thread Sleep(TimeSpan timeout)
		{
			Thread.Sleep(timeout);
			return Thread.CurrentThread;
		}
	}
}
